5-4 404页面&路由query&路径传参
404 页面(兜底路由)
当用户访问不存在的路由路径时,需要展示一个友好的 404 页面,而不是空白页面。
创建 404 组件
// src/pages/NotFound.tsx
import { Link } from 'react-router-dom';
export default function NotFound() {
return (
<div>
<h1>404 - 页面不存在</h1>
<p>您访问的页面不存在,请检查 URL 是否正确</p>
<Link to="/">返回首页</Link>
</div>
);
}
tsx
配置兜底路由
在 React Router v6 中,使用 path="*" 匹配所有未命中的路由:
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="*" element={<NotFound />} /> {/* 兜底路由,放在最后 */}
</Route>
</Routes>
tsx
关键点: 兜底路由需要放在 <Layout> 路由的子级中,这样 404 页面也能继承布局(导航栏、页脚等)。如果将 path="*" 放在 <Layout> 外面,404 页面就不会有导航栏等公共 UI。
// 正确:404 在 Layout 内部
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
<Route path="*" element={<NotFound />} /> {/* 有导航栏 */}
</Route>
// 错误:404 在 Layout 外部
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="about" element={<About />} />
</Route>
<Route path="*" element={<NotFound />} /> {/* 没有导航栏,看起来不一致 */}
tsx
路径参数(Path Params)
路径参数是 URL 中动态的部分,用 :paramName 标记:
// 路由配置
<Route path="/users/:id" element={<UserDetail />} />
<Route path="/posts/:postId/comments/:commentId" element={<Comment />} />
tsx
使用 useParams 获取参数
import { useParams } from 'react-router-dom';
function UserDetail() {
const { id } = useParams<{ id: string }>();
// 访问 /users/123 → id = "123"
// 访问 /users/abc → id = "abc"
return <div>用户 ID: {id}</div>;
}
tsx
多个路径参数
function Comment() {
const { postId, commentId } = useParams<{
postId: string;
commentId: string;
}>();
// 访问 /posts/5/comments/42 → postId = "5", commentId = "42"
return (
<div>
文章 ID: {postId},评论 ID: {commentId}
</div>
);
}
tsx
可选参数
v6 中可以使用 * 通配符实现灵活的路径匹配:
<Route path="/files/*" element={<FileManager />} />
function FileManager() {
const params = useParams();
// params['*'] 包含 * 匹配的所有内容
// 访问 /files/docs/readme.md → params['*'] = "docs/readme.md"
}
tsx
Query 参数(查询参数)
Query 参数是 URL 中 ? 后面的键值对:
/search?keyword=react&page=2&sort=latest
text
使用 useSearchParams
React Router v6 提供了 useSearchParams Hook 来操作 Query 参数,它的 API 类似 useState:
import { useSearchParams } from 'react-router-dom';
function SearchPage() {
const [searchParams, setSearchParams] = useSearchParams();
const keyword = searchParams.get('keyword') || '';
const page = parseInt(searchParams.get('page') || '1', 10);
const handleSearch = (newKeyword: string) => {
setSearchParams({ keyword: newKeyword, page: '1' });
};
const handlePageChange = (newPage: number) => {
setSearchParams({ keyword, page: String(newPage) });
};
return (
<div>
<input
value={keyword}
onChange={(e) => handleSearch(e.target.value)}
placeholder="搜索关键词"
/>
<p>当前搜索: {keyword},第 {page} 页</p>
<button onClick={() => handlePageChange(page + 1)}>下一页</button>
</div>
);
}
tsx
常用操作
const [searchParams, setSearchParams] = useSearchParams();
// 读取单个参数
searchParams.get('keyword'); // 'react' 或 null
searchParams.getAll('tag'); // ['js', 'ts'](多值参数)
// 检查参数是否存在
searchParams.has('page'); // true / false
// 修改参数(会更新 URL)
setSearchParams({ keyword: 'vue', page: '1' });
// 追加参数(不覆盖其他参数)
searchParams.set('page', '2');
setSearchParams(searchParams);
// 删除参数
searchParams.delete('page');
setSearchParams(searchParams);
tsx
三种传参方式对比
| 方式 | URL 示例 | 获取方式 | 适用场景 |
|---|---|---|---|
| 路径参数 | /users/123 | useParams() | 标识资源的唯一 ID |
| Query 参数 | /search?q=react | useSearchParams() | 筛选、排序、分页等可选参数 |
| State 传参 | 无 URL 变化 | useLocation().state | 不希望暴露在 URL 中的数据 |
State 传参
// 发送方
import { useNavigate } from 'react-router-dom';
function UserList() {
const navigate = useNavigate();
return (
<button onClick={() => navigate('/detail', { state: { from: 'list' } })}>
查看详情
</button>
);
}
// 接收方
import { useLocation } from 'react-router-dom';
function Detail() {
const location = useLocation();
const state = location.state as { from: string };
// state.from = 'list'
}
tsx
State 传参不会在 URL 中体现,刷新页面后数据会丢失(适合临时传递数据)。
↑